home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_300
/
366_01
/
ue311c1.arc
/
DISPLAY.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-10-25
|
37KB
|
1,675 lines
/*
* The functions in this file handle redisplay. There are two halves, the
* ones that update the virtual display screen, and the ones that make the
* physical display screen the same as the virtual display screen. These
* functions use hints that are left in the windows by the commands.
*
*/
#include <stdio.h>
#include "estruct.h"
#include "eproto.h"
#include "edef.h"
#include "elang.h"
typedef struct VIDEO {
int v_flag; /* Flags */
#if COLOR
int v_fcolor; /* current forground color */
int v_bcolor; /* current background color */
int v_rfcolor; /* requested forground color */
int v_rbcolor; /* requested background color */
#endif
#if INSDEL && MEMMAP == 0
int v_rline; /* requested screen line # */
#endif
char v_text[1]; /* Screen data. */
} VIDEO;
#define VFCHG 0x0001 /* Changed flag */
#define VFEXT 0x0002 /* extended (beyond column 80) */
#define VFREV 0x0004 /* reverse video status */
#define VFREQ 0x0008 /* reverse video request */
#define VFCOL 0x0010 /* color change requested */
static VIDEO **vscreen; /* Virtual screen. */
#if MEMMAP == 0
static VIDEO **pscreen; /* Physical screen. */
#endif
/* some local function declarations */
#if PROTO
#if MEMMAP
extern PASCAL NEAR updateline(int row, struct VIDEO *vp1);
#else
extern PASCAL NEAR updateline(int row, struct VIDEO *vp1, struct VIDEO *vp2);
#endif
#else
extern PASCAL NEAR updateline();
#endif
/*
* Initialize the data structures used by the display code. The edge vectors
* used to access the screens are set up. The operating system's terminal I/O
* channel is set up. All the other things get initialized at compile time.
* The original window has "WFCHG" set, so that it will get completely
* redrawn on the first call to "update".
*/
PASCAL NEAR vtinit()
{
register int i;
register VIDEO *vp;
TTopen(); /* open the screen */
TTkopen(); /* open the keyboard */
TTrev(FALSE);
/* allocate the virtual screen pointer array */
vscreen = (VIDEO **) malloc(term.t_mrow*sizeof(VIDEO *));
if (vscreen == NULL)
meexit(1);
#if MEMMAP == 0
/* allocate the physical shadow screen array */
pscreen = (VIDEO **) malloc(term.t_mrow*sizeof(VIDEO *));
if (pscreen == NULL)
meexit(1);
#endif
/* for every line in the display */
for (i = 0; i < term.t_mrow; ++i) {
/* allocate a virtual screen line */
vp = (VIDEO *) malloc(sizeof(VIDEO)+term.t_mcol);
if (vp == NULL)
meexit(1);
vp->v_flag = 0; /* init change clags */
#if COLOR
vp->v_rfcolor = 7; /* init fore/background colors */
vp->v_rbcolor = 0;
#endif
/* connect virtual line to line array */
vscreen[i] = vp;
#if MEMMAP == 0
/* allocate and initialize physical shadow screen line */
vp = (VIDEO *) malloc(sizeof(VIDEO)+term.t_mcol);
if (vp == NULL)
meexit(1);
vp->v_flag = 0;
#if INSDEL
vp->v_rline = i; /* set requested line position */
#endif
pscreen[i] = vp;
#endif
}
}
#if CLEAN
/* free up all the dynamically allocated video structures */
PASCAL NEAR vtfree()
{
int i;
for (i = 0; i < term.t_mrow; ++i) {
free(vscreen[i]);
#if MEMMAP == 0
free(pscreen[i]);
#endif
}
free(vscreen);
#if MEMMAP == 0
free(pscreen);
#endif
}
#endif
/*
* Clean up the virtual terminal system, in anticipation for a return to the
* operating system. Move down to the last line and clear it out (the next
* system prompt will be written in the line). Shut down the channel to the
* terminal.
*/
PASCAL NEAR vttidy()
{
mlerase();
movecursor(term.t_nrow, 0);
TTflush();
TTclose();
TTkclose();
}
/*
* Set the virtual cursor to the specified row and column on the virtual
* screen. There is no checking for nonsense values; this might be a good
* idea during the early stages.
*/
PASCAL NEAR vtmove(row, col)
int row, col;
{
vtrow = row;
vtcol = col;
}
/* Write a character to the virtual screen. The virtual row and
column are updated. If we are not yet on left edge, don't print
it yet. If the line is too long put a "$" in the last column.
This routine only puts printing characters into the virtual
terminal buffers. Only column overflow is checked.
*/
PASCAL NEAR vtputc(c)
int c;
{
register VIDEO *vp; /* ptr to line being updated */
vp = vscreen[vtrow];
if (c == '\t') {
do {
vtputc(' ');
} while (((vtcol + taboff) % (tabsize)) != 0);
} else if (vtcol >= term.t_ncol) {
++vtcol;
vp->v_text[term.t_ncol - 1] = '$';
} else if (disphigh && c > 0x7f) {
vtputc('^');
vtputc('!');
c -= 0x80;
if (c == '\t') {
vtputc('^');
vtputc('I');
} else
vtputc(c);
} else if (c < 0x20 || c == 0x7F) {
vtputc('^');
vtputc(c ^ 0x40);
} else {
if (vtcol >= 0)
vp->v_text[vtcol] = c;
++vtcol;
}
}
/*
* Erase from the end of the software cursor to the end of the line on which
* the software cursor is located.
*/
PASCAL NEAR vteeol()
{
register VIDEO *vp;
vp = vscreen[vtrow];
while (vtcol < term.t_ncol) {
if (vtcol >= 0)
vp->v_text[vtcol] = ' ';
vtcol++;
}
}
/* upscreen: user routine to force a screen update
always finishes complete update */
PASCAL NEAR upscreen(f, n)
int f,n; /* prefix flag and argument */
{
update(TRUE);
return(TRUE);
}
/*
* Make sure that the display is right. This is a three part process. First,
* scan through all of the windows looking for dirty ones. Check the framing,
* and refresh the screen. Second, make sure that "currow" and "curcol" are
* correct for the current window. Third, make the virtual and physical
* screens the same.
*/
PASCAL NEAR update(force)
int force; /* force update past type ahead? */
{
register WINDOW *wp;
#if TYPEAH
if (force == FALSE && typahead())
return(TRUE);
#endif
#if VISMAC == 0
if (force == FALSE && kbdmode == PLAY)
return(TRUE);
#endif
/* update any windows that need refreshing */
wp = wheadp;
while (wp != NULL) {
if (wp->w_flag) {
/* if the window has changed, service it */
reframe(wp); /* check the framing */
if ((wp->w_flag & ~WFMODE) == WFEDIT)
updone(wp); /* update EDITed line */
else if (wp->w_flag & ~WFMOVE)
updall(wp); /* update all lines */
if (wp->w_flag & WFMODE)
modeline(wp); /* update modeline */
wp->w_flag = 0;
wp->w_force = 0;
}
#if 1 /* take this out before the release! */
if (wp->w_wndp == wheadp) { /* erroneously circular list */
wp->w_wndp = (WINDOW *)NULL;
mlwrite("DAN!!! a bogus circular window list!!!");
TTgetc();
}
#endif
/* on to the next window */
wp = wp->w_wndp;
}
/* recalc the current hardware cursor location */
updpos();
#if MEMMAP
/* update the cursor and flush the buffers */
movecursor(currow, curcol - lbound);
#endif
/* check for lines to de-extend */
upddex();
/* if screen is garbage, re-plot it */
if (sgarbf != FALSE)
if (gflags & GFSDRAW)
sgarbf = FALSE;
else
updgar();
/* update the virtual screen to the physical screen */
updupd(force);
/* update the cursor and flush the buffers */
movecursor(currow, curcol - lbound);
TTflush();
return(TRUE);
}
/* reframe: check to see if the cursor is on in the window
and re-frame it if needed or wanted */
PASCAL NEAR reframe(wp)
WINDOW *wp;
{
register LINE *lp; /* search pointer */
register LINE *rp; /* reverse search pointer */
register LINE *hp; /* ptr to header line in buffer */
register LINE *tp; /* temp debugging pointer */
register int i; /* general index/# lines to scroll */
register int nlines; /* number of lines in current window */
/* figure out our window size */
nlines = wp->w_ntrows;
if (modeflag == FALSE)
nlines++;
/* if not a requested reframe, check for a needed one */
if ((wp->w_flag & WFFORCE) == 0) {
lp = wp->w_linep;
for (i = 0; i < nlines; i++) {
/* if the line is in the window, no reframe */
if (lp == wp->w_dotp)
return(TRUE);
/* if